#include <stdlib.h>
#include <stdio.h>
#include "func.h"

char help[] = "  get:  get a file frome server\n"
			  "  put:  upload a file to server\n"
			  "	 pwd:  display the current directory of server\n"
			  "	 dir:  display the files in the current directory of server\n"
			  "	 cd:   change the directory of server\n"
			  "	 ?:    display the whole command which equals 'help'\n"
			  "	 quit: quit the ftp server\n";
char currentDirPath[200];
char currentDirName[30];


extern void cmd_pwd(int sock)
{
	int len;
	char *savePointer;

	memset(currentDirPath, '\0', sizeof(currentDirPath));
	getcwd(currentDirPath, sizeof(currentDirPath));
	savePointer = getDirName(currentDirPath);
	len = strlen(currentDirName ) + 1;
	write(sock, currentDirName, len);
}

extern void cmd_dir(int sock)
{
	DIR *pdir;
	char fileName[30];
	char fileInfo[50];
	char filePath[200];
	int i, fcounts = 0;
	int fd;
	struct dirent *pent;
	struct stat fileSta;

	pdir = opendir(currentDirPath);
	pent = readdir(pdir);

	//统计目录和文件总数
	while (pent != NULL) {
		fcounts++;
		pent = readdir(pdir);
	}

	write(sock, &fcounts, sizeof(int));
	closedir(pdir);

	if (fcounts <= 0) {
		return;
	}
	else {
		pdir = opendir(currentDirPath);
		for (i = 0; i < fcounts; i++) {
			pent = readdir(pdir);
			memset(fileName, '\0', 30);
			memset(fileInfo, 0, sizeof(fileInfo));
			strcpy(fileName, pent->d_name);

			/* check the file is a directory or a file */
			memset(filePath, 0, sizeof(filePath));
			strcpy(filePath, currentDirPath);
			strcat(filePath, "/");
			strcat(filePath, fileName);				
			fd = open(filePath, O_RDONLY, S_IREAD);

			fstat(fd, &fileSta);
			if (S_ISDIR(fileSta.st_mode)) {		/* 目录 */
				strcat(fileInfo, "dir\t");
				strcat(fileInfo, fileName);
			}
			else {									/* 文件 */
				strcat(fileInfo, "file\t");
				strcat(fileInfo, fileName);
			}
			write(sock, fileInfo, sizeof(fileInfo));
		}

		closedir(pdir);
	}
}

extern void cmd_cd(int sock, char *dirName)
{
	DIR *pdir;
	struct dirent *pent;

	/* char filename[30] */
	int i, fcounts = 0;
	int flag = 0;

	pdir = opendir(currentDirPath);
	pent = readdir(pdir);

	while (pent != NULL) {
		fcounts++;
		pent = readdir(pdir);
	}

	if (fcounts <= 0) {
		return;
	}
	else {
		pdir = opendir(currentDirPath);
		for (i = 0; i < fcounts; i++) {
			pent = readdir(pdir);
			if (strcmp(pent->d_name, dirName) == 0) {
				strcat(currentDirPath, "/");
				strcat(currentDirPath, dirName);
				flag = 1;
				break;
			}
		}

		if (flag == 1) {
			write(sock, currentDirPath, sizeof(currentDirPath));
		}
		closedir(pdir);
	}
}

extern void cmd_cdback(int sock)
{
	int len;
	int i;

	len = strlen(currentDirPath);

	for (i = len - 1; i >= 0; i--) {
		if (currentDirPath[i] == '/') {
			currentDirPath[i] = '\0';
			break;
		}
		currentDirPath[i] = '\0';
	}
}

extern void cmd_help(int sock)
{
	int len;
	len = strlen(help) + 1;
	write(sock, help, len);
}

extern void cmd_get(int sock, char *fileName)
{
	int fd;
	struct stat fileSta;
	long fileSize;
	char filePath[200], buf[dataLen];

	memset(filePath, '\0', sizeof(filePath));
	strcpy(filePath, currentDirPath);
	strcat(filePath, "/");
	strcat(filePath, fileName);

	fd = open(filePath, O_RDONLY, S_IREAD);
	if (fd != -1) {
		fstat(fd, &fileSta);
		fileSize = (long) fileSta.st_size;
		write(sock, &fileSize, sizeof(long)); 

		memset(buf, '\0', dataLen);
		while (fileSize > dataLen) {
			read(fd, buf, dataLen);
			write(sock, buf, dataLen);
			fileSize = fileSize - dataLen;
		}

		read(fd, buf, fileSize);
		write(sock, buf, fileSize);
		close(fd);
		printf("transfer completed\n");
	}
	else {
		printf("open file %s failed\n", filePath);
	}
}

extern void cmd_put(int sock, char *fileName)
{
	int fd;
	long fileSize;
	char filePath[200], buf[dataLen];

	strcpy(filePath, currentDirPath);
	strcat(filePath, "/");
	strcat(filePath, fileName);

	fd = open(filePath, O_RDWR | O_CREAT, S_IREAD | S_IWRITE);
	if (fd != -1) {
		memset(buf, '\0', dataLen);
		read(sock, &fileSize, sizeof(long));		/* 读入上传文件大小 */

		while (fileSize > dataLen) {
			read(sock, buf, dataLen);
			write(fd, buf, dataLen);
			fileSize = fileSize - dataLen;
		}

		read(sock, buf, fileSize);
		write(fd, buf, fileSize);
		close(fd);
		printf("transfer completed\n");
	}
	else {
		printf("Open file %s failed\n", filePath);
	}
}

extern char *getDirName(char *dirPathName)
{
	int i, pos, len;
	char *dirName;

	if (dirPathName == NULL) {
		printf("directory absoultly path is null\n");
		return NULL;
	}

	len = strlen(dirPathName);
	for (i = len - 1; i >= 0; i--) {
		if (dirPathName[i] == '/') {
			pos = i;
			break;
		}
	}

	dirName = (char *)malloc(len - pos + 1);
	for (i = pos + 1; i < len; i++) {
		dirName[i - pos - 1] = dirPathName[i];
	}

	return dirName;
}
